package com.lambkit.plugin.undertow;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.net.NetUtil;
import cn.hutool.setting.Setting;
import com.lambkit.core.LambkitApp;
import com.lambkit.core.LifecycleException;
import com.lambkit.core.pipeline.DefaultPipeLineFactory;
import com.lambkit.core.task.http.HttpWorkCenter;
import com.lambkit.plugin.http.HttpPlugin;
import com.lambkit.core.service.impl.DefaultBeanFactory;
import com.lambkit.core.service.impl.DefaultClassOperateFactory;
import com.lambkit.core.service.impl.DefaultResourceFactory;
import io.undertow.Handlers;
import io.undertow.Undertow;
import io.undertow.server.handlers.PathHandler;
import io.undertow.servlet.Servlets;
import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.api.DeploymentManager;

import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import java.util.Iterator;
import java.util.LinkedHashSet;

/**
 * @author yangyong(孤竹行)
 */
public class UndertowApp extends LambkitApp {

    private Undertow undertowServer;
    private DeploymentManager deploymentManager;

    private TimeInterval timer = DateUtil.timer();

    public UndertowApp(String name) {
        super(name);
        context().setBeanFactory(new DefaultBeanFactory());
        context().setClassOperateFactory(new DefaultClassOperateFactory());
        context().setPipeLineFactory(new DefaultPipeLineFactory());
        context().setResourceFactory(new DefaultResourceFactory());
    }

    @Override
    public void start() throws LifecycleException {
        //初始化工作中心
        HttpWorkCenter workCenter = new HttpWorkCenter();
        context().addWorkCenter(workCenter.runOn(this));
        context().addPlugin(new HttpPlugin());
        super.start();
    }

    @Override
    public void postStart() throws LifecycleException {
        Setting setting = new Setting("undertow.txt");
        int port = setting.getInt("undertow.port", 8080);
        //undertow
        DeploymentInfo servletBuilder = Servlets.deployment()
                .setClassLoader(UndertowApp.class.getClassLoader())
                .setContextPath("/")
                .setDeploymentName("lambkit")
                .addFilter(Servlets.filter("lambkit", ServletFilter.class)
                        .addInitParam("appName", context().getName()))
                .addFilterUrlMapping("lambkit", "/*", DispatcherType.REQUEST);

        deploymentManager = Servlets.defaultContainer().addDeployment(servletBuilder);
        deploymentManager.deploy();
        PathHandler path = null;
        try {
            path = Handlers.path(Handlers.redirect("/"))
                    .addPrefixPath("/", deploymentManager.start());
        } catch (ServletException e) {
            throw new RuntimeException(e);
        }

        undertowServer = Undertow.builder()
                .addHttpListener(port, "localhost")
                .setHandler(path)
                .build();
        undertowServer.start();
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        System.out.println("Lambkit Undertow Server Starting Complete in " + timer.interval() + "ms.");
        super.postStart();

        String msg = "Server running on:\n";
        msg = msg + " > Local:   http://localhost:" + port;
        msg = msg + "\n";
        LinkedHashSet<String> ipList = NetUtil.localIpv4s();
        for(Iterator iterator = ipList.iterator(); iterator.hasNext(); msg = msg + "\n") {
            String ip = (String)iterator.next();
            msg = msg + " > Network: http://" + ip + ":" + port;
        }
        System.out.println(msg);
    }

    @Override
    public void stop() throws LifecycleException {
        super.stop();
        if(deploymentManager != null) {
            try {
                deploymentManager.stop();
            } catch (ServletException e) {
                throw new RuntimeException(e);
            }
        }
        if(undertowServer != null) {
            undertowServer.stop();
        }
    }
}
